home *** CD-ROM | disk | FTP | other *** search
/ Joystick Magazine 2002 October / JOY141_CD2.iso / Data / Sharewares / Graphisme / Nimo50Build8.exe / Div Fix / Source / DivX.pas < prev   
Pascal/Delphi Source File  |  2002-03-16  |  24KB  |  803 lines

  1. {DivFix is a utility for reindexing partial DivX AVI movies
  2. Copyright (C) 2000-2002  Csaba Budai
  3.  
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8.  
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  12. GNU General Public License for more details.
  13.  
  14. You should have received a copy of the GNU General Public License
  15. along with this program; if not, write to the Free Software
  16. Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA}
  17.  
  18. unit DivX;
  19.  
  20. interface
  21.  
  22. uses
  23.   Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  24.   StdCtrls, Mask, Menus, ExtCtrls, Buttons, DropSource, DropTarget,
  25.   ComCtrls;
  26.  
  27. type
  28.   TForm1 = class(TForm)
  29.     Button1: TButton;
  30.     Button2: TButton;
  31.     Button3: TButton;
  32.     MaskEdit1: TMaskEdit;
  33.     OpenDialog1: TOpenDialog;
  34.     MainMenu1: TMainMenu;
  35.     File1: TMenuItem;
  36.     Help1: TMenuItem;
  37.     About1: TMenuItem;
  38.     Open1: TMenuItem;
  39.     Regenerate1: TMenuItem;
  40.     Strip1: TMenuItem;
  41.     Exit1: TMenuItem;
  42.     Panel1: TPanel;
  43.     SpeedButton1: TSpeedButton;
  44.     Memo1: TMemo;
  45.     Window1: TMenuItem;
  46.     Stayontop1: TMenuItem;
  47.     DropFileTarget1: TDropFileTarget;
  48.     ProgressBar1: TProgressBar;
  49.     Check1: TMenuItem;
  50.     Stop: TButton;
  51.     CheckBox1: TCheckBox;
  52.     CheckBox2: TCheckBox;
  53.     procedure SpeedButton1Click(Sender: TObject);
  54.     procedure Button1Click(Sender: TObject);
  55.     procedure Button2Click(Sender: TObject);
  56.     procedure Exit1Click(Sender: TObject);
  57.     procedure About1Click(Sender: TObject);
  58.     procedure StayTop(Sender: TObject);
  59.     procedure FormCreate(Sender: TObject);
  60.     procedure FormDestroy(Sender: TObject);
  61.     procedure DropFileTarget1Drop(Sender: TObject; ShiftState: TShiftState;
  62.       Point: TPoint; var Effect: Integer);
  63.     procedure Button3Click(Sender: TObject);
  64.     procedure StopClick(Sender: TObject);
  65.     procedure CheckBox1Click(Sender: TObject);
  66.  
  67.   private
  68.     { Private declarations }
  69.   public
  70.       Input,Output        : File;
  71.     Backup                    :    File;
  72.         i,j                            :    Cardinal;
  73.         Size,Position        :    Cardinal;
  74.         StreamStart            :    Cardinal;
  75.     StreamSize            :    Cardinal;
  76.     Difference            :    Cardinal;
  77.     Frame                        :    Cardinal;
  78.     Interleaved     : Boolean;
  79.     OnTop                        :    Boolean;
  80.     StopButton            :    Boolean;
  81.         Chunkname                :    String[8];
  82.         Temp                        : integer;
  83.         FrameType                :    Byte;
  84.         Buffer                    :    Array [1..32800] Of Byte;
  85.     Text                        : String;
  86.   end;
  87.  
  88.   Const
  89.       KeyFrame  :    Longint = 16;
  90.     NormFrame    :    Longint = 0;
  91.     Number        :    Set of char =['0'..'9'];
  92.  
  93. var
  94.   Form1: TForm1;
  95.  
  96. implementation
  97.  
  98. uses About;
  99.  
  100. {$R *.DFM}
  101.  
  102. procedure DisableButtons;
  103. begin
  104.     Form1.MaskEdit1.Enabled:=False;
  105.     Form1.Button1.Enabled:=False;
  106.   Form1.Button2.Enabled:=False;
  107.   Form1.Button3.Enabled:=False;
  108.   Form1.CheckBox1.Enabled:=False;
  109.   Form1.CheckBox2.Enabled:=False;
  110. end;
  111.  
  112. procedure EnableButtons;
  113. begin
  114.     Form1.MaskEdit1.Enabled:=True;
  115.      Form1.Button1.Enabled:=True;
  116.   Form1.Button2.Enabled:=True;
  117.   Form1.Button3.Enabled:=True;
  118.   Form1.CheckBox1.Enabled:=True;
  119.   If Form1.CheckBox1.Checked Then Form1.CheckBox2.Enabled:=True;
  120. end;
  121.  
  122. procedure TForm1.SpeedButton1Click(Sender: TObject);
  123. begin
  124.     If OpenDialog1.Execute Then MaskEdit1.Text:=OpenDialog1.FileName;
  125. end;
  126.  
  127. procedure TForm1.Button1Click(Sender: TObject);
  128. Var k    :    Cardinal;
  129. Label BError;
  130. Label BStartRead;
  131. begin
  132.     DisableButtons;
  133.     If MaskEdit1.Text='' Then
  134.   Begin
  135.         Memo1.Lines.Insert(0,' No file selected.');
  136.     EnableButtons;
  137.       Exit;
  138.   End;
  139.     AssignFile(Input,MaskEdit1.Text);
  140.     AssignFile(Output,'$TEMP.IDX');
  141.   AssignFile(Backup,MaskEdit1.Text+'.DivFix');
  142.   {$I-}
  143.     Reset(Input,1);
  144.     {$I+}
  145.     Temp:=IOResult;
  146.   If Temp<>0 Then
  147.     Begin
  148.       If (Temp=3) Or (Temp=2) Then Memo1.Lines.Insert(0,' File not found.')
  149.     Else
  150.         If Temp=5 Then Memo1.Lines.Insert(0,' The file is write-protected.')
  151.         Else Memo1.Lines.Insert(0,' Can not open the file.');
  152.         EnableButtons;
  153.     Exit;
  154.   End;
  155.   Seek(Input,8);
  156.   BlockRead(Input,ChunkName[1],8,Temp);
  157.   ChunkName[0]:=#8;
  158.   If ChunkName<>'AVI LIST' Then
  159.   Begin
  160.       Memo1.Lines.Insert(0,' This is not an AVI file.');
  161.     CloseFile(Input);
  162.     EnableButtons;
  163.     Exit;
  164.   End;
  165.     {$I-}
  166.     Rewrite(Output,1);
  167.     {$I+}
  168.     If IOResult<>0 Then
  169.     Begin
  170.         Memo1.Lines.Insert(0,' Cannot create temporary index file.');
  171.     CloseFile(Input);
  172.     EnableButtons;
  173.     Exit;
  174.   End;
  175.     If CheckBox1.Checked Then
  176.   Begin
  177.       AssignFile(Backup,MaskEdit1.Text+'.DivFix');
  178.         {$I-}
  179.         Rewrite(Backup,1);
  180.         {$I+}
  181.         If IOResult<>0 Then
  182.         Begin
  183.             Memo1.Lines.Insert(0,' Cannot create backup file.');
  184.         CloseFile(Input);
  185.         CloseFile(Output);
  186.       If CheckBox1.Checked Then CloseFile(Backup);
  187.         Erase(Output);
  188.         EnableButtons;
  189.         Exit;
  190.       End;
  191.   End;
  192.     Memo1.Lines.Insert(0,' Rebuilding index...');
  193.      Position:=16;
  194.   Size:=0;
  195.      Chunkname[0]:=#4;
  196.   Repeat
  197.          Position:=Position+Size;
  198.       Seek(Input,Position);
  199.     BlockRead(Input,Size,4);
  200.        BlockRead(Input,Chunkname[1],4);
  201.        Inc(Position,8);
  202.   Until Chunkname='movi';
  203.      StreamStart:=Position-4;
  204.   StreamSize:=Size;
  205.      Chunkname:='idx1';
  206.   BlockWrite(Output,Chunkname[1],4);
  207.      BlockWrite(Output,Size,4);
  208.   Position:=4;
  209.      i:=0;
  210.   Frame:=0;
  211.   Difference:=0;
  212.   Interleaved:=False;
  213.   StopButton:=False;
  214.   Seek(Input,0);
  215.   If CheckBox1.Checked Then
  216.   Begin
  217.       BlockRead(Input,Buffer[1],StreamStart+4,Temp);
  218.       BlockWrite(Backup,Buffer[1],Temp);
  219.   End;
  220.   Repeat
  221.     ProgressBar1.Position:=Position Div (FileSize(Input) Div 100);
  222.          Seek(Input,StreamStart+Position);
  223.        If Not Eof(Input) Then
  224.     Begin
  225.             BStartRead:
  226.           BlockRead(Input,Chunkname[1],4,Temp);
  227.       If ChunkName='LIST' Then
  228.       Begin
  229.           Seek(Input,FilePos(Input)+8);
  230.         Inc(Position,12);
  231.         Goto BStartRead;
  232.             End;
  233.       If ChunkName='JUNK' Then
  234.       Begin
  235.           BlockRead(Input,Size,4);
  236.         Position:=Position+Size+8;
  237.           Seek(Input,StreamStart+Position);
  238.                 Goto BStartRead;
  239.             End;
  240.       If (Copy(ChunkName,1,2)='ix') Or (Copy(ChunkName,3,2)='ix') Then
  241.       Begin
  242.           Seek(Input,FilePos(Input)+12);
  243.         Inc(Position,16);
  244.           Seek(Input,StreamStart+Position);
  245.         Interleaved:=True;
  246.         Goto BStartRead;
  247.             End;
  248.       If Not Eof(Input) Then
  249.       Begin
  250.           If ((ChunkName[1] In Number) And (ChunkName[2] In Number)) And
  251.            ((Copy(ChunkName,3,2)='dc') Or (Copy(ChunkName,3,2)='db') Or
  252.            (Copy(ChunkName,3,2)='wb')) Then
  253.         Begin
  254.             Inc(Frame);
  255.           If Interleaved Then
  256.           Begin
  257.               Seek(Input,FilePos(Input)-16);
  258.             Dec(Position,16);
  259.             Interleaved:=False;
  260.           End;
  261.                   BlockRead(Input,Size,4,Temp);
  262.           If (Size<0) And (Temp=4) Then
  263.           Begin
  264.               Inc(Position,4);
  265.             Seek(Input,StreamStart+Position);
  266.             BlockRead(Input,Chunkname[1],4,Temp);
  267.             If ChunkName='LIST' Then
  268.                   Begin
  269.                       Seek(Input,FilePos(Input)+8);
  270.               Inc(Position,12);
  271.                             Goto BStartRead;
  272.                         End;
  273.             If ChunkName='JUNK' Then
  274.                   Begin
  275.                       BlockRead(Input,Size,4);
  276.                     Position:=Position+Size+8;
  277.                       Seek(Input,StreamStart+Position);
  278.                     Goto BStartRead;
  279.                         End;
  280.             Seek(Input,StreamStart+Position);
  281.             Goto BError;
  282.                     End;
  283.               If Not Eof(Input) Then
  284.               Begin
  285.                       BlockRead(Input,FrameType,1);
  286.                   j:=(((Position+Size) Div 2)+((Position+Size) Mod 2))*2+8;
  287.                      Seek(Input,StreamStart+j-1);
  288.                      If Not Eof(Input) Then
  289.                   Begin
  290.                           BlockWrite(Output,Chunkname[1],4);
  291.                           If ((Copy(ChunkName,3,2)='dc') Or (Copy(ChunkName,3,2)='db') Or
  292.                  (Copy(ChunkName,3,2)='wb')) And ((Chunkname[1]In Number) And
  293.                  (ChunkName[2] In Number)) And (FrameType And 64=0)
  294.               Then
  295.                   BlockWrite(Output,KeyFrame,4)
  296.                           Else
  297.                   BlockWrite(Output,NormFrame,4);
  298.                           If CheckBox2.Checked Then
  299.               Begin
  300.                   j:=Position-Difference;
  301.                   BlockWrite(Output,j,4)
  302.               End
  303.               Else BlockWrite(Output,Position,4);
  304.                           BlockWrite(Output,Size,4);
  305.               j:=Position;
  306.                            Position:=(((Position+Size) Div 2)+((Position+Size) Mod 2))*2+8;
  307.               Seek(Input,StreamStart+j);
  308.               If CheckBox1.Checked Then
  309.               Begin
  310.                   If Position-j>32768 Then
  311.                   Begin
  312.                       For k:=1 To (Position-j) Div 32768 Do
  313.                     Begin
  314.                                         BlockRead(Input,Buffer[1],32768,Temp);
  315.                           BlockWrite(Backup,Buffer[1],Temp);
  316.                       End;
  317.                     BlockRead(Input,Buffer[1],((Position-j) Mod 32768),Temp);
  318.                          BlockWrite(Backup,Buffer[1],Temp);
  319.                   End
  320.                   Else
  321.                   Begin
  322.                       BlockRead(Input,Buffer[1],Position-j,Temp);
  323.                       BlockWrite(Backup,Buffer[1],Temp);
  324.                   End;
  325.               End;
  326.                         Inc(i);
  327.                      End;
  328.                    End;
  329.         End
  330.         Else
  331.             BError:
  332.           If Chunkname<>'idx1' Then
  333.           Begin
  334.               Str(Frame,Text);
  335.                 Text:=' Corrupted data detected at frame '+Text;
  336.               If FilePos(Output)>16 Then Seek(Output,FilePos(Output)-16);
  337.                         Memo1.Lines.Insert(0,Text);
  338.             Str(StreamStart+Position,Text);
  339.             Text:=' Error offset: '+Text;
  340.             Memo1.Lines.Insert(0,Text);
  341.             j:=Position;
  342.               Repeat
  343.                   Seek(Input,StreamStart+Position);
  344.                 If Not Eof(Input) Then
  345.                 Begin
  346.                         BlockRead(Input,Buffer[1],32768,Temp);
  347.                 k:=1;
  348.                   Repeat
  349.                           If ((Chr(Buffer[k])='d') Or (Chr(Buffer[k])='w')) And (Not Eof(Input)) Then
  350.                         Begin
  351.                               If ((Chr(Buffer[k+1])='c') Or (Chr(Buffer[k+1])='b')) And (Not Eof(Input)) Then
  352.                          Begin
  353.                             Seek(Input,StreamStart+Position+k-3);
  354.                              If Not Eof(Input) Then BlockRead(Input,ChunkName[1],4);
  355.                            End;
  356.                          End;
  357.                         Inc(k);
  358.                                 Until (((Copy(ChunkName,3,2)='dc') Or (Copy(ChunkName,3,2)='db') Or
  359.                           (Copy(ChunkName,3,2)='wb')) And ((ChunkName[1] In Number) And
  360.                           (ChunkName[2] In Number))) Or (Chunkname='idx1') Or (k>32768);
  361.                   End;
  362.               Inc(Position,k-3);
  363.                           Application.ProcessMessages;
  364.                           If StopButton Then
  365.                           Begin
  366.                               Memo1.Lines.Insert(0,' Index rebuilding aborted...');
  367.                             ProgressBar1.Position:=0;
  368.                             StopButton:=False;
  369.                                 CloseFile(Input);
  370.                                 CloseFile(Output);
  371.                 If CheckBox1.Checked Then CloseFile(Backup);
  372.                                  Erase(Output);
  373.                 EnableButtons;
  374.                                Exit;
  375.                           End;
  376.               Until (((Copy(ChunkName,3,2)='dc') Or (Copy(ChunkName,3,2)='db') Or
  377.                   (Copy(ChunkName,3,2)='wb')) And ((ChunkName[1] In Number) And
  378.                   (ChunkName[2] In Number))) Or (Chunkname='idx1') Or Eof(Input);
  379.                  If Not Eof(Input) Then Dec(Position);
  380.                         If CheckBox1.Checked Then
  381.             Begin
  382.                 If Not(CheckBox2.Checked) Then
  383.               Begin
  384.                     Seek(Input,StreamStart+j);
  385.                     If Position-j>32768 Then
  386.                     Begin
  387.                       For k:=1 To (Position-j) Div 32768 Do
  388.                        Begin
  389.                                         BlockRead(Input,Buffer[1],32768,Temp);
  390.                           BlockWrite(Backup,Buffer[1],Temp);
  391.                          End;
  392.                        BlockRead(Input,Buffer[1],((Position-j) Mod 32768),Temp);
  393.                             BlockWrite(Backup,Buffer[1],Temp);
  394.                   End
  395.                     Else
  396.                     Begin
  397.                         BlockRead(Input,Buffer[1],Position-j,Temp);
  398.                         BlockWrite(Backup,Buffer[1],Temp);
  399.                     End;
  400.               End
  401.               Else Difference:=Difference+Position-j;
  402.             End;
  403.           End
  404.           Else
  405.           Begin
  406.               Seek(Input,FilePos(Input)+6);
  407.             ChunkName[0]:=#2;
  408.             BlockRead(Input,ChunkName[1],2);
  409.             Seek(Input,FilePos(Input)-8);
  410.             If (ChunkName='dc') Or (ChunkName='wb') Or (ChunkName='db') Then
  411.             Begin
  412.                 ChunkName[0]:=#4;
  413.               ChunkName:='idx1';
  414.             End
  415.             Else
  416.             Begin
  417.                 ChunkName[0]:=#4;
  418.               ChunkName:='0000';
  419.               Goto BError;
  420.             End
  421.           End;
  422.       End;
  423.     End;
  424.     Application.ProcessMessages;
  425.     If StopButton Then
  426.     Begin
  427.         Memo1.Lines.Insert(0,' Index rebuilding aborted...');
  428.       ProgressBar1.Position:=0;
  429.       StopButton:=False;
  430.           CloseFile(Input);
  431.              CloseFile(Output);
  432.       If CheckBox1.Checked Then CloseFile(Backup);
  433.           Erase(Output);
  434.       EnableButtons;
  435.         Exit;
  436.     End;
  437.     Until (Eof(Input)) Or (ChunkName='idx1');
  438.      Size:=i*16;
  439.   Seek(Output,4);
  440.      BlockWrite(Output,Size,4);
  441.     If CheckBox1.Checked Then
  442.   Begin
  443.       StreamSize:=Filesize(Backup)-StreamStart;
  444.       Seek(Backup,StreamStart-4);
  445.          BlockWrite(Backup,StreamSize,4);
  446.       Seek(Backup,StreamStart+StreamSize);
  447.          Seek(Output,0);
  448.       Repeat
  449.              BlockRead(Output,Buffer[1],32768,Temp);
  450.            BlockWrite(Backup,Buffer[1],Temp);
  451.         Until Not(Temp=32768);
  452.       Truncate(Backup);
  453.       CloseFile(Input);
  454.          CloseFile(Output);
  455.     CloseFile(Backup);
  456.       Erase(Output);
  457.   End
  458.   Else
  459.   Begin
  460.       StreamSize:=Filesize(Input)-StreamStart;
  461.       Seek(Input,StreamStart-4);
  462.          BlockWrite(Input,StreamSize,4);
  463.       Seek(Input,StreamStart+StreamSize);
  464.          Seek(Output,0);
  465.       Repeat
  466.              BlockRead(Output,Buffer[1],32768,Temp);
  467.            BlockWrite(Input,Buffer[1],Temp);
  468.         Until Not(Temp=32768);
  469.       Truncate(Input);
  470.       CloseFile(Input);
  471.          CloseFile(Output);
  472.       Erase(Output);
  473.   End;
  474.     Memo1.Lines.Insert(0,' Done.');
  475.   EnableButtons;
  476. end;
  477.  
  478. procedure TForm1.Button2Click(Sender: TObject);
  479. begin
  480.     DisableButtons;
  481.   If Maskedit1.Text='' Then
  482.   Begin
  483.         Memo1.Lines.Insert(0,' No file selected.');
  484.     EnableButtons;
  485.       Exit;
  486.   End;
  487.     AssignFile(Input,MaskEdit1.Text);
  488.   {$I-}
  489.     Reset(Input,1);
  490.     {$I+}
  491.   If Not (IOResult=0) Then
  492.     Begin
  493.       If (Temp=3) Or (Temp=2) Then Memo1.Lines.Insert(0,' File not found.')
  494.     Else
  495.         If Temp=5 Then Memo1.Lines.Insert(0,' The file is write-protected.')
  496.         Else Memo1.Lines.Insert(0,' Can not open the file.');
  497.     EnableButtons;
  498.     Exit;
  499.   End;
  500.   Seek(Input,8);
  501.   BlockRead(Input,ChunkName[1],8);
  502.   ChunkName[0]:=#8;
  503.   If ChunkName<>'AVI LIST' Then
  504.   Begin
  505.         Memo1.Lines.Insert(0,' This is not an AVI file.');
  506.     CloseFile(Input);
  507.     EnableButtons;
  508.     Exit;
  509.   End;
  510.   Memo1.Lines.Insert(0,' Stripping index...');
  511.      Position:=16;
  512.   Size:=0;
  513.      Chunkname[0]:=#4;
  514.   Repeat
  515.          Position:=Position+Size;
  516.       Seek(Input,Position);
  517.     BlockRead(Input,Size,4);
  518.        BlockRead(Input,Chunkname[1],4);
  519.        Inc(Position,8);
  520.   Until Chunkname='movi';
  521.      StreamStart:=Position-4;
  522.   StreamSize:=Size;
  523.   Seek(Input,StreamStart+StreamSize);
  524.   If Eof(Input) Then
  525.   Begin
  526.       Memo1.Lines.Insert(0,' Unexpected end of file, index not found.');
  527.     CloseFile(Input);
  528.     EnableButtons;
  529.     Exit;
  530.   End;
  531.     Truncate(Input);
  532.   Seek(Input,StreamStart-4);
  533.     BlockWrite(Input,StreamSize,4);
  534.   CloseFile(Input);
  535.     Memo1.Lines.Insert(0,' Done.');
  536.     EnableButtons;
  537. end;
  538.  
  539. procedure TForm1.Button3Click(Sender: TObject);
  540. Label CError;
  541. Label CStartRead;
  542.  
  543. begin
  544.     DisableButtons;
  545.     If MaskEdit1.Text='' Then
  546.   Begin
  547.         Memo1.Lines.Insert(0,' No file selected.');
  548.     EnableButtons;
  549.       Exit;
  550.   End;
  551.     AssignFile(Input,MaskEdit1.Text);
  552.   {$I-}
  553.     Reset(Input,1);
  554.     {$I+}
  555.     Temp:=IOResult;
  556.   If Temp<>0 Then
  557.     Begin
  558.       If (Temp=3) Or (Temp=2) Then Memo1.Lines.Insert(0,' File not found.')
  559.     Else
  560.         If Temp=5 Then Memo1.Lines.Insert(0,' The file is write-protected.')
  561.         Else Memo1.Lines.Insert(0,' Can not open the file.');
  562.     EnableButtons;
  563.     Exit;
  564.   End;
  565.   Seek(Input,8);
  566.   BlockRead(Input,ChunkName[1],8);
  567.   ChunkName[0]:=#8;
  568.   If ChunkName<>'AVI LIST' Then
  569.   Begin
  570.       Memo1.Lines.Insert(0,' This is not an AVI file.');
  571.     CloseFile(Input);
  572.     EnableButtons;
  573.     Exit;
  574.   End;
  575.     Memo1.Lines.Insert(0,' Checking Errors...');
  576.   Memo1.Lines.Insert(0,' NOTE: The error checking is not perfect!');
  577.      Position:=16;
  578.   Size:=0;
  579.      Chunkname[0]:=#4;
  580.   Repeat
  581.          Position:=Position+Size;
  582.       Seek(Input,Position);
  583.     BlockRead(Input,Size,4);
  584.        BlockRead(Input,Chunkname[1],4);
  585.        Inc(Position,8);
  586.   Until Chunkname='movi';
  587.      StreamStart:=Position-4;
  588.   StreamSize:=Size;
  589.      Chunkname:='idx1';
  590.   Position:=4;
  591.      i:=0;
  592.   Frame:=0;
  593.   Interleaved:=False;
  594.   StopButton:=False;
  595.   Repeat
  596.     ProgressBar1.Position:=Position Div (FileSize(Input) Div 100);
  597.          Seek(Input,StreamStart+Position);
  598.        If Not Eof(Input) Then
  599.     Begin
  600.         CStartRead:
  601.           BlockRead(Input,Chunkname[1],4,Temp);
  602.       If ChunkName='LIST' Then
  603.       Begin
  604.           Seek(Input,FilePos(Input)+8);
  605.         Inc(Position,12);
  606.         Goto CStartRead;
  607.             End;
  608.       If ChunkName='JUNK' Then
  609.       Begin
  610.           BlockRead(Input,Size,4);
  611.         Position:=Position+Size+8;
  612.           Seek(Input,StreamStart+Position);
  613.         Goto CStartRead;
  614.             End;
  615.       If (Copy(ChunkName,1,2)='ix') Or (Copy(ChunkName,3,2)='ix') Then
  616.       Begin
  617.           Seek(Input,FilePos(Input)+12);
  618.         Inc(Position,16);
  619.           Seek(Input,StreamStart+Position);
  620.         Interleaved:=True;
  621.         Goto CStartRead;
  622.             End;
  623.       If Not Eof(Input) Then
  624.       Begin
  625.           If ((ChunkName[1] In Number) And (ChunkName[2] In Number)) And
  626.            ((Copy(ChunkName,3,2)='dc') Or (Copy(ChunkName,3,2)='db') Or
  627.            (Copy(ChunkName,3,2)='wb')) Then
  628.         Begin
  629.             Inc(Frame);
  630.           If Interleaved Then
  631.           Begin
  632.               Seek(Input,FilePos(Input)-16);
  633.             Dec(Position,16);
  634.             Interleaved:=False;
  635.           End;
  636.                   BlockRead(Input,Size,4,Temp);
  637.           If (Size<0) And (Temp=4) Then
  638.           Begin
  639.               Inc(Position,4);
  640.             Seek(Input,StreamStart+Position);
  641.             BlockRead(Input,Chunkname[1],4);
  642.                   If ChunkName='LIST' Then
  643.                   Begin
  644.                       Seek(Input,FilePos(Input)+8);
  645.               Inc(Position,12);
  646.                     Goto CStartRead;
  647.                         End;
  648.             If ChunkName='JUNK' Then
  649.                   Begin
  650.                       BlockRead(Input,Size,4);
  651.                     Position:=Position+Size+8;
  652.                       Seek(Input,StreamStart+Position);
  653.                     Goto CStartRead;
  654.                         End;
  655.             Seek(Input,StreamStart+Position);
  656.             Goto CError;
  657.           End;
  658.               If Not Eof(Input) Then
  659.               Begin
  660.                       BlockRead(Input,FrameType,1);
  661.                   j:=(((Position+Size) Div 2)+((Position+Size) Mod 2))*2+8;
  662.                      Seek(Input,StreamStart+j-1);
  663.                      If Not Eof(Input) Then
  664.                   Begin
  665.                            Position:=(((Position+Size) Div 2)+((Position+Size) Mod 2))*2+8;
  666.                         Inc(i);
  667.                      End;
  668.                    End;
  669.         End
  670.         Else
  671.                     CError:
  672.           If Chunkname<>'idx1' Then
  673.           Begin
  674.               Str(Frame,Text);
  675.                 Text:=' Corrupted data detected at frame '+Text;
  676.                         Memo1.Lines.Insert(0,Text);
  677.             Str(StreamStart+Position,Text);
  678.             Text:=' Error offset: '+Text;
  679.             Memo1.Lines.Insert(0,Text);
  680.               Repeat
  681.                   Seek(Input,StreamStart+Position);
  682.                 If Not Eof(Input) Then
  683.                 Begin
  684.                         BlockRead(Input,Buffer[1],32768,Temp);
  685.                 j:=1;
  686.                   Repeat
  687.                           If ((Chr(Buffer[j])='d') Or (Chr(Buffer[j])='w')) And (Not Eof(Input)) Then
  688.                         Begin
  689.                               If ((Chr(Buffer[j+1])='c') Or (Chr(Buffer[j+1])='b')) And (Not Eof(Input)) Then
  690.                          Begin
  691.                             Seek(Input,StreamStart+Position+j-3);
  692.                              If Not Eof(Input) Then BlockRead(Input,ChunkName[1],4);
  693.                            End;
  694.                          End;
  695.                         Inc(j);
  696.                                 Until (((Copy(ChunkName,3,2)='dc') Or (Copy(ChunkName,3,2)='db') Or
  697.                           (Copy(ChunkName,3,2)='wb')) And ((ChunkName[1] In Number) And
  698.                           (ChunkName[2] In Number))) Or (Chunkname='idx1') Or (j>32768);
  699.                   End;
  700.               Inc(Position,j-3);
  701.               Application.ProcessMessages;
  702.                         If StopButton Then
  703.                         Begin
  704.                             Memo1.Lines.Insert(0,' Error checking aborted...');
  705.                           ProgressBar1.Position:=0;
  706.                           StopButton:=False;
  707.                 CloseFile(Input);
  708.                 EnableButtons;
  709.                             Exit;
  710.                         End;
  711.               Until (((Copy(ChunkName,3,2)='dc') Or (Copy(ChunkName,3,2)='db') Or
  712.                   (Copy(ChunkName,3,2)='wb')) And ((ChunkName[1] In Number) And
  713.                   (ChunkName[2] In Number))) Or (Chunkname='idx1') Or Eof(Input);
  714.               If Not Eof(Input) Then Dec(Position);
  715.             End
  716.           Else
  717.           Begin
  718.               Seek(Input,FilePos(Input)+6);
  719.             ChunkName[0]:=#2;
  720.             BlockRead(Input,ChunkName[1],2);
  721.             Seek(Input,FilePos(Input)-8);
  722.             If (ChunkName='dc') Or (ChunkName='wb') Or (ChunkName='db') Then
  723.             Begin
  724.                 ChunkName[0]:=#4;
  725.               ChunkName:='idx1';
  726.             End
  727.             Else
  728.             Begin
  729.                 ChunkName[0]:=#4;
  730.               ChunkName:='0000';
  731.               Goto CError;
  732.             End
  733.           End;
  734.       End;
  735.     End;
  736.     Application.ProcessMessages;
  737.     If StopButton Then
  738.     Begin
  739.         Memo1.Lines.Insert(0,' Error checking aborted...');
  740.       ProgressBar1.Position:=0;
  741.       StopButton:=False;
  742.       CloseFile(Input);
  743.         Exit;
  744.     End;
  745.     Until (Eof(Input)) Or (ChunkName='idx1');
  746.   CloseFile(Input);
  747.     Memo1.Lines.Insert(0,' Done.');
  748.     EnableButtons;
  749. end;
  750.  
  751. procedure TForm1.Exit1Click(Sender: TObject);
  752. begin
  753.     Close;
  754. end;
  755.  
  756. procedure TForm1.About1Click(Sender: TObject);
  757. begin
  758.     Form2.Show;
  759. end;
  760.  
  761. procedure TForm1.StayTop(Sender: TObject);
  762. begin
  763.     If Stayontop1.Checked Then
  764.   Begin
  765.       Stayontop1.Checked:=Not(Stayontop1.Checked);
  766.     SetWindowPos(TForm1(Self).Handle,HWND_NOTOPMOST,0,0,0,0,SWP_NOSIZE+SWP_NOMOVE);
  767.   End
  768.   Else
  769.   Begin
  770.       Stayontop1.Checked:=Not(Stayontop1.Checked);
  771.     SetWindowPos(TForm1(Self).Handle,HWND_TOPMOST,0,0,0,0,SWP_NOSIZE+SWP_NOMOVE);
  772.   End;
  773. end;
  774.  
  775. procedure TForm1.FormCreate(Sender: TObject);
  776. begin
  777.     DropFileTarget1.register(Form1)
  778. end;
  779.  
  780. procedure TForm1.FormDestroy(Sender: TObject);
  781. begin
  782.     DropFiletarget1.Unregister;
  783. end;
  784.  
  785. procedure TForm1.DropFileTarget1Drop(Sender: TObject;
  786.   ShiftState: TShiftState; Point: TPoint; var Effect: Integer);
  787. begin
  788.     MaskEdit1.Text:=DropFileTarget1.files[0];
  789. end;
  790.  
  791. procedure TForm1.StopClick(Sender: TObject);
  792. begin
  793.     StopButton:=True;
  794. end;
  795.  
  796. procedure TForm1.CheckBox1Click(Sender: TObject);
  797. begin
  798.   CheckBox2.Enabled:=Not(CheckBox2.Enabled);
  799.   If Not(CheckBox2.Enabled) Then CheckBox2.Checked:=False;
  800. end;
  801.  
  802. end.
  803.